//--------------------------------------------------------------------------------------
// File: Tutorial07.fx
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------

//--------------------------------------------------------------------------------------
// Constant Buffer Variables
//--------------------------------------------------------------------------------------
Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );
Texture3D voxelTexture : register( t1 );
SamplerState voxelSamplerLinear : register( s1 );

cbuffer cbNeverChanges : register( b0 )
{
    matrix View;
};

cbuffer cbChangeOnResize : register( b1 )
{
    matrix Projection;
};

cbuffer cbChangesEveryFrame : register( b2 )
{
    matrix World;
};


//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float4 Pos : POSITION;
//    float3 Normal : NORMAL;
    float2 Tex : TEXCOORD0;
};

struct PS_INPUT
{
    uint z8_y8_x8_case8 : TEXCOORD0;
    
};


//--------------------------------------------------------------------------------------
// Geometry Shader
//--------------------------------------------------------------------------------------
float4 MultiplyMatrices( float4 input )
{
    float4 output = input;
    output = mul( input, World );
    output = mul( output, View );
    output = mul( output, Projection );

    
    return output;
}

float3 VertexInterp(float3 p1, float3 p2, float val1, float val2)
{
    float mu = (0.5f - val1) / (val2 - val1);
    float3 p = lerp(p1, p2, mu);
    return p;
}
uint GetMarker(float3 voxelPos, float isolevel, int vtype)
{

	/*if( vtype == 0 )
	{
		return;
	}*/
	
	float texelSize = 1.0f / 33.0f;
	voxelPos += 0.5f;
	
    float4 val0 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos), 0);
    float4 val1 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(1,0,0)), 0);
    float4 val2 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(1,1,0)), 0);
    float4 val3 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(0,1,0)), 0);
    float4 val4 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(0,0,1)), 0);
    float4 val5 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(1,0,1)), 0);
    float4 val6 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(1,1,1)), 0);
    float4 val7 = voxelTexture.SampleLevel(voxelSamplerLinear, texelSize * (voxelPos+float3(0,1,1)), 0);

    uint cubeindex = 0;

    if (val0.r >= isolevel) cubeindex |= 1;
    if (val1.r >= isolevel) cubeindex |= 2;
    if (val2.r >= isolevel) cubeindex |= 4;
    if (val3.r >= isolevel) cubeindex |= 8;
    if (val4.r >= isolevel) cubeindex |= 16;
    if (val5.r >= isolevel) cubeindex |= 32;
    if (val6.r >= isolevel) cubeindex |= 64;
    if (val7.r >= isolevel) cubeindex |= 128;	
	
	return cubeindex;
   
}
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
    PS_INPUT output = (PS_INPUT)0;
	int3 intPos = (int3)round ( input.Pos );

	
	output.z8_y8_x8_case8 = GetMarker(input.Pos.xyz, 0.5f, 0);
	output.z8_y8_x8_case8 |= (intPos.z << 24) | (intPos.y << 16) | (intPos.x << 8);
  
    return output;
}

[maxvertexcount(1)]
void GS( point PS_INPUT input[1], inout PointStream<PS_INPUT> triStream )
{
	uint cube_case = (input[0].z8_y8_x8_case8 & 0xFF);
	if (cube_case * (255-cube_case) > 0)
	{
		PS_INPUT output;
		output.z8_y8_x8_case8 = input[0].z8_y8_x8_case8;
		
		triStream.Append(output);
	}
	
}
